home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Pascal Super Library
/
Pascal Super Library (CW International)(1997).bin
/
TURB_VIS
/
TVLIST
/
DEMO.PAS
next >
Wrap
Pascal/Delphi Source File
|
1991-03-16
|
28KB
|
734 lines
Program ListDemo;
{********************************************************************
* LISTDEMO *
* This program provides a simple demonstration of using the TVLIST *
* unit for Turbo Vision TCollection class objects. Refer to *
* TVLIST.DOC for documentation. *
* *
* Problem : Your store has list of merchandise. For your inventory*
* system you want to be able to maintain these lists, as *
* well as use the list to create invoices. (Well it is *
* just a demo!) *
* *
* *
* Copyright 1991 McQuay Technologies *
* 2329 E. Cortez Phoenix AZ 85028 *
* 100 Sycamore Richmond TX *
* Prodigy ID WPTD01E Compuserve 72307,320 *
* Released into the Public Domain, Give Credit were Credit Is Due *
* *
********************************************************************}
uses Objects, app, Drivers, Menus, Views, Dialogs, TVList, MsgBox;
{===============================================================
User List Basics
---------------------------------------------------------------
TMyRecord Class
This object Class provides the basic element for your list. It
provides slots fon each item.
===============================================================}
type
PMyRecord = ^TMyRecord;
TMyRecord = object(TObject)
Partname:Pstring;
PartCode:word;
inventory:word;
Price:real;
constructor init(AName:string;APartCode,NumberOnHand:word;APrice:real);
destructor done; virtual;
procedure Store(var S:TStream); virtual;
procedure Load(var S:TStream); virtual;
end;
{===============================================================
TMyList Class
This class is a descendant of TSortedList which is a descendant of
TSortedCollection. It is a sorted list of PMyRecord. Keyof()
and Compare() provide the QSORT like routines needed for
TSortedCollection to maintain a sorted list. GetItemText()
retrieves a string for each record. Since each record of MyRecord
is not a string record it must convert the MyRecord slots to
string values for display. CreatItem() and EditItem() are
methods that allow the editing of PMyRecord records using
dialog boxes.
===============================================================}
type
PMyList = ^TMyList;
TMyList = Object(TSortedList)
function KeyOf(Item:pointer):pointer; virtual;
function Compare(Key1,Key2:pointer):integer; virtual;
function GetItemText(item:pointer;MaxLen:word):string; virtual;
function CreateItem(Corner:Tpoint):pointer; virtual;
procedure editItem(Corner:Tpoint;Item:pointer); virtual;
End;
{===============================================================
TMyOtherList Class
This class is a descendant of TList which is a descendant of
TCollection. It is a list of PMyRecord. GetItemText()
retrieves a string for each record. Since each record of MyRecord
is not a string record it must convert the MyRecord slots to
string values for display. CreatItem() and EditItem() are
methods that allow the editing of PMyRecord records using
dialog boxes. Very similar to TMyList.
===============================================================}
type
PMyOtherList = ^TMyOtherList;
TMyOtherList = Object(TList)
function GetItemText(item:pointer;MaxLen:word):string; virtual;
function CreateItem(Corner:Tpoint):pointer; virtual;
procedure editItem(Corner:Tpoint;Item:pointer); virtual;
End;
{ This is a header used with TMyRecord Lists for display of each
records data. This matches how GetItemText() formats each
records data. }
const
MyBoxHeader = 'Part Name Code Stock Price';
{===============================================================
TMyRecord Methods
===============================================================}
constructor TMyRecord.init
(AName:string;APartCode,NumberOnHand:word;APrice:real);
begin
PartName := NewStr(AName);
PartCode := APartCode;
Inventory:= NumberOnHand;
Price := APrice;
end;
{----------------------------}
destructor TMyRecord.done;
begin
disposeStr(PArtName);
end;
{----------------------------}
procedure TMyRecord.Store(var S:TStream);
begin
S.writeStr(PartName);
S.write(PartCode,sizeof(PartCode));
S.Write(Inventory,Sizeof(Inventory));
S.write(Price,sizeof(Price));
end;
{----------------------------}
procedure TMyRecord.Load(var S:TStream);
begin
Partname := S.readStr;
S.read(PartCode,sizeof(PartCode));
S.read(Inventory,Sizeof(Inventory));
S.read(Price,sizeof(Price));
end;
{---------------------------------------------------------
Dialog Setup Info
This is info used in a generic Dialog Box for editing
PMyRecord data. This provides info on the location
and labeling of the various fields.
---------------------------------------------------------}
Type
TPartsDialogSetup = record
FS:byte; { Field Size }
L:Pstring;{ Label }
Y:byte; { Y of Field }
end;
Fields = (PartName,PartCode,PartInventory,PartPrice);
Const
{ Size if Input Fields }
PartNameSize = 20;
PartCodeSize = 5;
PartPriceSize = 6;
PartInventorySize = 5;
{ Label for each field }
SPartNameLabel: string = 'Part Name';
SPartCodeLabel: string = 'Part Code';
SPartInventoryLabel: string = 'Inventory';
SPartPriceLabel: string = 'Part Price @';
{ An array of location, size, and labeling info for each field
FS = FieldSize L = @ to a Label Y =line in Dialog for field}
PD : array[PartName..PartPrice] of TPartsDialogSetup =
( (FS:PartNameSize;L:@SPartNameLabel;Y:2),
(FS:PartCodeSize;L:@SPartCodeLabel;Y:4),
(FS:PartInventorySize;L:@SPartInventoryLabel;Y:6),
(FS:PartPriceSize;L:@SPartPriceLabel;Y:8) );
{---------------------------------
This procedure provides a Generic
Dialog Box to edit a TMyRecord
class instance.
---------------------------------}
procedure TMyList_EditDialog(TD:Pdialog; var P:PMyRecord);
var
{ Record used to set and Get Data from Dialog }
DataRecord: record
SPartname:STring[PartNameSize];
SPartCode:String[PartCodeSize];
Sinventory:String[PartInventorySize];
SPrice:String[PartPriceSIze];
end;
{ pointers used for inserting Fields }
TV:PView;
TL:PLabel;
{ Used to locate Fields }
R:Trect;
{ A loop interator }
Field:Fields;
{ Used in data conversion }
Err:word;
Aword:Word;
Areal:Real;
begin
{ Set Up Main Dialog }
{ Loop through field const Array and setup Fields }
with TD^ do
begin
for Field := PartName to PartPrice do
with PD[Field] do
begin
R.Assign(2,Y,FS+5,Y+1);
TV := new(PInputLine, init(R,FS));
insert(TV);
R.Assign(2,y-1,Length(L^)+3,Y);
insert(new(Plabel,init(R,L^,TV)));
end;
{ Setup OK and Cancel Buttons }
R.assign(2,10,20,12);
Insert(new(PButton, init(R,'Ok',cmOk,bfNormal)));
R.assign(23,10,40,12);
Insert(new(PButton, init(R,'Cancel',cmCancel,bfDefault)));
{ Skip to first field }
SelectNext(False);
{ setup initial data }
with P^ do
with DataRecord do
begin
if PartName <> nil then
SPartName := Copy(PartName^,1,PartNAmeSize)
else
SPArtName := '';
str(PartCode:PartCodeSize,SPartCode);
str(Inventory:PartInventorySize,SInventory);
str(Price:PartPriceSize:2,SPrice);
end;
SetData(DataRecord);
end;
{ OK execute dialog and check if cmOk returned }
if DeskTop^.execview(TD) = cmOk then
with P^ do
begin
{ Ok New Data, let's get it }
TD^.GetData(DataRecord);
{ It is all strings so lets place in our Object }
with DataRecord do
begin
{ PartName }
if PartName<>nil then
disposestr(PartName);
PartName := newStr(SPartName);
{ Part Code }
val(SPartCode,Aword,err);
if Err=0 then
PartCode := Aword
else
PartCode := 0;
{ Part Inventory }
val(SInventory,Aword,err);
if Err=0 then
Inventory := Aword
else
Inventory := 0;
{ Part Price }
val(SPrice,AReal,err);
if Err=0 then
Price := AReal
else
Price := 0.0;
end;
end;
end;
{===============================================================
TMyList Methods
===============================================================}
{ Sort on Partname }
function TMyList.KeyOf(Item:pointer):pointer;
begin
keyof := PMyRecord(item)^.Partname;
end;
{----------------------------}
function TMyList.Compare(Key1,Key2:pointer):integer;
begin
if pstring(key1)^ = pstring(key2)^ then
Compare:=0
else
if pstring(key1)^ < pstring(key2)^ then
Compare := -1
else
Compare := 1;
end;
{----------------------------}
{ This converts to strings the data fields of a PMyRecord object
and formats it into a string for display in a lIst Box. }
function TMyList.GetItemText(item:pointer;MaxLen:word):string;
var
S,SW:string;
begin
S:=PMyRecord(Item)^.partname^;
if length(S)<PartNameSize then
begin
fillchar(S[Length(S)+1],PartNameSize-length(S),32);
S[0] := char(PartNameSize);
end
else
S:=copy(S,1,PartNameSize);
str(PMyRecord(Item)^.PartCode:PartCodeSize,Sw);
S := S+Sw;
str(PMyRecord(Item)^.Inventory:PartInventorySize,Sw);
S := S+Sw;
str(PMyRecord(Item)^.Price:PartPriceSize:2,Sw);
S := S+' $'+Sw;
GetItemText := copy(S,1,MaxLen);
end;
{----------------------------}
{ Uses TMyList_EditDialog to create a PMyRecord instance }
function TMyList.CreateItem(Corner:Tpoint):pointer;
var
P:PMyRecord;
TD:PDialog;
R:Trect;
begin
{ initialize a blank record }
P:=new(PMyRecord, init('',0,0,0.0));
{ Calculate Dialog Location }
MakeTrect(Corner,50,15,R);
TD := new(PDialog, init(R,'Parts Inventory Record'));
TMyList_EditDialog(TD,P);
{ If canceled then Partname will be nil and cancel create }
If P^.PartName = nil then
begin
P^.done;
CreateItem := nil;
end
else
CreateItem := P;
end;
{----------------------------}
{ Uses TMyList_EditDialog to edit a PMyRecord instance }
procedure TMyList.editItem(Corner:Tpoint;Item:pointer);
var
TD:PDialog;
R:trect;
begin
MakeTrect(Corner,50,15,R);
TD := new(PDialog, init(R,'Parts Inventory Record'));
TMyList_EditDialog(TD,PMyRecord(Item));
end;
{----------------------------}
{===============================================================
TMyOtherList Methods
===============================================================}
{----------------------------}
{ This converts to strings the data fields of a PMyRecord object
and formats it into a string for display in a list Box. }
function TMyOtherList.GetItemText(item:pointer;MaxLen:word):string;
var
S,SW:string;
begin
S:=PMyRecord(Item)^.partname^;
if length(S)<PartNameSize then
begin
fillchar(S[Length(S)+1],PartNameSize-length(S),32);
S[0] := char(PartNameSize);
end
else
S:=copy(S,1,PartNameSize);
str(PMyRecord(Item)^.PartCode:PartCodeSize,Sw);
S := S+Sw;
str(PMyRecord(Item)^.Inventory:PartInventorySize,Sw);
S := S+Sw;
str(PMyRecord(Item)^.Price:PartPriceSize:2,Sw);
S := S+' $'+Sw;
GetItemText := copy(S,1,MaxLen);
end;
{----------------------------}
{ Uses TMyList_EditDialog to create a PMyRecord instance }
function TMyOtherList.CreateItem(Corner:TPoint):pointer;
var
P:PMyRecord;
TD:Pdialog;
R:Trect;
begin
{ initialize a blank record }
P:=new(PMyRecord, init('',0,0,0.0));
{ Let the user fill it in }
MakeTrect(Corner,50,15,R);
TD := new(PDialog, init(R,'Parts Inventory Record'));
TMyList_EditDialog(TD,P);
{ If canceled then Partname will be nil and cancel create }
If P^.PartName = nil then
begin
P^.done;
CreateItem := nil;
end
else
CreateItem := P;
end;
{----------------------------}
{ Uses TMyList_EditDialog to edit a PMyRecord instance }
procedure TMyOtherList.editItem(Corner:TPoint;Item:pointer);
var
TD:PDialog;
R:Trect;
begin
TD := new(PDialog, init(R,'Parts Inventory Record'));
TMyList_EditDialog(TD,PMyRecord(Item));
end;
{----------------------------}
{===========================================================
Main Application
This is the main application
===========================================================}
const
cmDialog1 = $3000;
cmDialog2 = $3002;
cmDialog3 = $3003;
cmDialog4 = $3004;
type
TMyApp = object(TApplication)
procedure HandleEvent(var Event: TEvent); virtual;
procedure InitMenuBar; virtual;
procedure InitStatusLine; virtual;
end;
{-------------------------------------------------------------
Here are our lists and our support ListDialogs
-------------------------------------------------------------}
Var
MyList:PMyList;
MyOtherList:PMyOtherList;
TestDialog:PListDialog;
TestSortedDialog : PSortedListDialog;
{-------------------------------------------------------------
This initializes our lists
-------------------------------------------------------------}
procedure MakeList;
begin
MyList := new(PMyList, init(10,2));
with MyList^ do
begin
{ Because this is a sorted list (TSortedCollection) we will use
insert. If it was not a sorted list we would use AtInsert(O,^) }
Insert(new(PMyRecord,init('McQuay List ToolBox',1,100,15.0)));
Insert(new(PMyRecord,init('Turbo Pascal Ver 6.0',2,1,99.0)));
Insert(new(PMyRecord,init('McQuay TV ToolBox',3,50,30.0)));
Insert(new(PMyRecord,init('Turbo Assembler',4,1,69.0)));
Insert(new(PMyRecord,init('Turbo C++',5,1,169.0)));
Insert(new(PMyRecord,init('Turbo Prolog',6,1,0.0)));
Insert(new(PMyRecord,init('Object Professional',7,1,99.0)));
Insert(new(PMyRecord,init('Turbo Debugger',8,1,99.0)));
end;
MyOtherList := new(PMyOtherList, init(10,2));
with MyOtherList^ do
begin
{ Because this is a not sorted list (TCollection) we will use
AtInsert(O,^) }
AtInsert(0,new(PMyRecord,init('Quattro Pro',10,1,100.0)));
AtInsert(0,new(PMyRecord,init('Paradox Ver 3.5',11,1,175.0)));
AtInsert(0,new(PMyRecord,init('Microsoft Word',12,1,250.0)));
AtInsert(0,new(PMyRecord,init('Windows 3.0',13,1,69.0)));
AtInsert(0,new(PMyRecord,init('dBase IV',14,1,400.0)));
AtInsert(0,new(PMyRecord,init('TimeLine ver 4',15,1,500.0)));
AtInsert(0,new(PMyRecord,init('PCTools 6',16,1,79.0)));
AtInsert(0,new(PMyRecord,init('Freelance',17,1,379.0)));
end;
end;
{------------------------------------------------------------------
These routines are the Demo Window Support
------------------------------------------------------------------}
const
MaxText = 9;
MaxDemo = 6;
type
DemoWindowText = array[0..MaxDemo,1..MaxText] of string;
const
DemoText : DemoWindowText =
( ('HI! Welcome to a demo of the TVLIST unit and Turbo Vision`s',
'TCollection and TListBox classes. The TVList unit provides',
'classes that are designed to make it easier to incorporate',
'TListBox and TCollection objects in your programs. TVlist,',
'classes make it easy to create user interfaces to select items',
'in a list (Collection) as well as editing, adding, and ',
'deleteing items in a list.',
'The F2, F3, F4, and F5 keys each are hotkeys to demos of TVList',
'objects. Watch this window for info on each demo. Have FUN!'),
('********** Class: TSortedList and TSortedListDialog *********',
'This dialog box has all available editing and selection',
'options enabled. The list box can be scrolled with the cursor',
'keys or mouse. Specific items can be found in the list box by',
'typing a search string, which appears above the box. As each',
'key is entered the list box scrolls to the closest matching',
'item. Each item when highlighted can be edited or deleted.',
'Deletes will prompt for appproval before deleting the item.',
'New items can be added. Try it then PRESS ESC'),
('++++++++++ Class: TSortedList and TSortedListDialog ++++++++',
'This dialog box has no editing features enabled, but does ',
'allow selection from the list box. The list box can be scrolled',
'with the cursor keys, mouse, or by typing a serach string.',
'Any item can be selected by double clicking on it with the',
'mouse, or by highlighting it and pressing the return key.',
'When an item is selected, the dialog can either simply exit',
'with that slection, or move to the OK Button for verification.',
'Try highlighting an item and then select it. Now verify OK.'),
('================= Class: TList and TListDialog ===============',
'This dialog is displaying an unsorted list. Here no editing',
'features are enabled. Right now try holding the mouse button',
'down and moving the cursor above the list box while the list',
'box is selected. Notice how the list box scrolls up. Now try',
'it below the list box. You can scroll with the cursor, pgup,',
'pgdn keys as well. You can select the highlighted item with the',
'Enter key or double click. With this box there is no verify',
'after an item is selected. Try it, highlight and select.'),
('----- Class: TList,TSortedList and TListDialogInputField -----',
'This dialog demonstrates an input field that can be inserted in',
'any Tdialog object. This is a descendant of TInputLine. When',
'selected it can be used to execute a TListDialog. Move to one',
'of the fields and press the INS key. A ListDialog for your',
'List is evoked. These are the same as the other three Demo',
'Dialogs so all capabilities are available. Even editing,',
'adding and deleting are available. Items can be selected and',
'text of the Item Selected will appear in the field. Try IT!'),
('',
'Here a TListDialog has been executed. Now you can use the full',
'features of the dialog. Select an item or cancel the dialog',
'and you will return to your original dialog box that you',
'designed. Try It!',
'',
'',
'',
''),
('',
'***************************************************************',
' Try another one! ',
'',
' Press F2, F4, F6, or F8',
'',
' Press Alt-X to Exit ',
'',
'***************************************************************')
);
type
PDemoWindow = ^TDemoWindow;
TDemoWindow = object(Twindow)
N:word;
procedure SetN(Demo:word);
procedure Draw; virtual;
end;
procedure TDemoWindow.SetN(Demo:word);
begin
N := Demo;
drawview;
end;
procedure TDemoWindow.draw;
var
i:word;
begin
Twindow.draw;
for i:=1 to MaxText do
writeStr(2,i,DemoText[N,i],1);
end;
Var
DemoWindow:PDemoWindow;
{------------------------------------------------------------------
This routine exercises our Lists, ListDialogs, and ListInputFields
------------------------------------------------------------------}
procedure ListInputFieldDialog;
var
MyDialog:PDialog;
R:Trect;
FCorner:Tpoint;
DCorner:Tpoint;
ReturnRecs : array[1..2] of TListRec;
Pl:Plabel;
Pb:PButton;
PLDIF:PListDialogInputField;
begin
R.assign(10,10,60,25);
MyDialog := new(Pdialog, init(R,'Dialog of Dialog of Lists'));
with MyDialog^ do
begin
{ Assign corner of Field }
FCorner.X := 2;
FCorner.Y := 2;
{ Assign corner of Dialog }
DCorner.X := 1;
DCorner.Y := 10;
PLDIF :=
new(PListDialogInputField,
init(FCorner,DCorner,12,
'Parts Edit',sfDoAll,MyList,MyBoxHeader,true));
insert(PLDIF);
R.Assign(2,1,40,2);
insert(new(PLabel,init(R,'Parts Edit/Entry',PLDIF)));
{ Assign corner of Field }
FCorner.X := 2;
FCorner.Y := 4;
PLDIF :=
new(PListDialogInputField,
init(Fcorner,DCorner,12,
'Parts Select',sfSearch,MyList,MyBoxHeader,true));
insert(PLDIF);
R.Assign(2,3,40,4);
insert(new(PLabel,init(R,'Parts Select',PLDIF)));
{ Assign corner of Field }
FCorner.X := 2;
FCorner.Y := 6;
PLDIF :=
new(PListDialogInputField,
init(Fcorner,DCorner,12,'Other Parts Select',
sfFullEdit,MyOtherList,MyBoxHeader,false));
insert(PLDIF);
R.Assign(2,5,40,6);
insert(new(PLabel,init(R,'OtherParts Select',PLDIF)));
R.Assign(2,8,12,10);
insert(new(PButton, init(R,'OK',cmOk,bfnormal)));
R.assign(14,8,26,10);
Insert(new(PButton, init(R,'Cancel',cmCancel,bfDefault)));
SelectNext(False);
end;
DemoWindow^.SetN(4);
Desktop^.Execview(MyDialog);
DemoWindow^.SetN(6);
end;
{-----------------------------------------------------------------}
procedure TestThoseDialogs(N:word);
var
R:Trect;
T:TListRec;
i:integer;
begin
R.Assign(10,10,0,0);
{ Start The Dialog List Box on the First Record by passing
SetData() a TListRec with indec=0 }
T.Index := 0;
case N of
{ Setup The TSortedListDialog to do all edit, add, delete,
with prompts on delete and move to OK for Exit after Select. }
1,2: begin
if N= 1 then i:= sfDoAll else i:=SfSearch+sfPromptExit;
TestSortedDialog := new(PSortedListDialog,
init(R,'Parts Inventory',i,PsortedList(MyList),
MyBoxHeader));
TestSortedDialog^.setData(T);
{ Ok Execute the ListDialog and save return Command }
DemoWindow^.SetN(N);
i := desktop^.ExecView(TestSortedDialog);
TestSortedDialog^.GetData(T);
end;
3: begin
{ Setup The TListDialog to just select with no prompting,
But since this is a sorted list, we will allow it to do incremental
searching. }
TestDialog :=
new(PListDialog,
init(R,'Parts Inventory',0,PList(MyOtherList),
MyBoxHeader));
TestDialog^.setData(T);
{ Ok Execute the ListDialog and save return Command }
DemoWindow^.SetN(N);
i := desktop^.ExecView(TestDialog);
TestDialog^.GetData(T);
end;
end;
{ Alright, if cmOk was returned and T.Item is not nil then
get the return index and do what is need, in this case
display a message. Normally, if the purpose of this Dialog
was just to edit,add,delete; then the return command would
have been ignored. }
if (I=cmOk) and (T.Item<>nil) then
begin
R.assign(15,8,75,15);
MessageBoxRect(R,'You Selected: %s',@PMyRecord(T.item)^.partName,
mfOKButton+mfInformation);
end;
DemoWindow^.SetN(6);
end;
{-------------------------------------------------------------------
This is the main application event handler. This is where all the
action is.
-------------------------------------------------------------------}
procedure TMyApp.HandleEvent(var Event: TEvent);
var
R:Trect;
I:word;
T:TListRec;
begin
TApplication.HandleEvent(Event);
if Event.What = evCommand then
begin
case Event.Command of
{ The Parts Edit Dialog }
cmDialog1:TestThoseDialogs(1);
{ The Parts Select Dialog }
cmDialog2:TestThoseDialogs(2);
CmDialog3:TestThoseDialogs(3);
CMDialog4:ListInputFieldDialog;
end;
ClearEvent(Event);
end;
end;
procedure TMyApp.InitMenuBar;
var R: TRect;
begin
GetExtent(R);
R.B.Y := R.A.Y + 1;
MenuBar := New(PMenuBar, Init(R, NewMenu(
NewSubmenu('~D~ialogs', hcNoContext,newmenu(
NewItem('Parts Edit Dialog','F2',kbF2,cmDialog1,hcNoContext,
newItem('Parts Pick Dialog','F4',kbF4,cmDialog2,hcNoContext,
newItem('Other Pick Dialog','F6',kbF6,cmDialog3,hcNoContext,
newItem('3 in 1 Dialog','F8',kbF8,cmDialog4,hcNoContext,
nil))))),nil)
)));
end;
procedure TMyApp.InitStatusLine;
var R: TRect;
begin
GetExtent(R);
R.A.Y := R.B.Y - 1;
StatusLine := New(PStatusLine, Init(R,
NewStatusDef(0, $FFFF,
NewStatusKey('', kbF10, cmMenu,
NewStatusKey('~Alt-X~ Exit', kbAltX, cmQuit,
NewStatusKey('~F2~ Parts Edit', kbF2, cmdialog1,
NewStatusKey('~F4~ Parts Select',kbF4, cmDialog2,
NewStatusKey('~F6~ Other Select',kbF6, cmDialog3,
NewStatusKey('~F8~ 3 in 1',kbF8, cmDialog4,
nil)))))),
nil)
));
end;
var
MyApp: TMyApp;
R:Trect;
begin
MakeList;
MyApp.Init;
R.Assign(7,0,73,11);
DemoWindow :=new(PdemoWindow,init(R,' TVList Demo',0));
Desktop^.insert(DemoWindow);
MyApp.Run;
MyApp.Done;
end.
{----------------------------------------------------}